package com.example.geguo.nettyclientchatdemo;

import android.content.Context;
import android.util.Log;

import com.example.geguo.nettyclientchatdemo.bean.QQMessage;
import com.example.geguo.nettyclientchatdemo.core.OnReceiveMsgListener;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * 作者： 13687
 * 创建日期：2017/6/25
 * 功能描述：管理一个长连接
 * ## 连接管理器有哪些状态呢?
 * 1. 死亡
 * 2. 运行
 * 3. 正在连接
 * ## 这些状态什么时候需要用到呢?
 *
 * 1. 建立连接的时候
 * 2. 断开连接的时候
 */

public class NettyConnectionManager{
	private static final String TAG ="NettyConnectionManager";
	private static NettyConnectionManager minaLongConnectManager;
	EventLoopGroup group = new NioEventLoopGroup();
	/**
	 * 长连接是否正在连接中...
	 * 异步的呢！channel.closeFuture().sync();//哈哈 我这里不让你走
	 */
	private static boolean isRunning = false;
	private static Context context;//检查应用是否还活着
	private Channel channel;

	public static synchronized NettyConnectionManager getInstance(Context ctx) {
		if (minaLongConnectManager == null) {
			context = ctx;
			minaLongConnectManager = new NettyConnectionManager();
		}
		return minaLongConnectManager;
	}


	public void run() {
		// 需要不断的改变状态(while 里面都是阻塞方法)
		while (isRunning){
			try {
				channel.closeFuture().sync();
				isRunning = false;
			} catch (InterruptedException e) {
				e.printStackTrace();
				isRunning = false;
			}
		}

	}

	// 添加多个监听
	private List<OnReceiveMsgListener> listeners = new ArrayList<OnReceiveMsgListener>();

	public void addOnReceiveMsgListener(OnReceiveMsgListener listener) {
		listeners.add(listener);
	}

	public void removeOnReceiveMsgListener(OnReceiveMsgListener listener) {
		listeners.remove(listener);
	}

	public void sendMsg(String msg){
		if (checkConnectStatus()){
			channel.writeAndFlush(msg+ "\r\n");
		}
	}



	public synchronized void startConnect(){
		    isRunning = beginConnect();
		    run();
	}

	private static ExecutorService executorService = Executors.newSingleThreadExecutor();
	/**
	 * 1. 异步
	 * 2. 连接成功以前
	 * */
	private boolean beginConnect(){
		FutureTask<Boolean> futureTask = new FutureTask<>(new Callable<Boolean>() {
			@Override
			public Boolean call() {
				try {
					Bootstrap bootstrap  = new Bootstrap()
							.group(group)
							.channel(NioSocketChannel.class)
							.handler(new ChannelInitializer<SocketChannel>() {
								@Override
								protected void initChannel(SocketChannel ch) throws Exception {
									ChannelPipeline pipeline = ch.pipeline();
									pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
									pipeline.addLast("decoder", new StringDecoder());
									pipeline.addLast("encoder", new StringEncoder());
									pipeline.addLast("handler", new SimpleChannelInboundHandler<String>() {
										@Override
										protected void channelRead0(ChannelHandlerContext channelHandlerContext, final String xml) throws Exception {
										/*		try {
													QQMessage msg = new QQMessage();
													msg = (QQMessage) msg.fromXml(xml);
													if (msg != null) {
														for (OnReceiveMsgListener listener : listeners) {
															listener.onReceive(msg);
														}
													}
												} catch (Exception e) {
													e.printStackTrace();
												}*/
											Log.d(TAG, "channelRead0: "+xml);
											for (OnReceiveMsgListener listener : listeners) {
												listener.onReceive(xml);
											}
										}
									});
								}
							});
					channel = bootstrap.connect("192.168.0.104", 8080).sync().channel();
					return channel.isActive();
				} catch (InterruptedException e) {
					e.printStackTrace();
					return false;
				}
			}
		});

		executorService.submit(futureTask);

		try {
			return futureTask.get();
		} catch (Exception e) {
			return false;
		}

	}
	public boolean checkConnectStatus(){
		return !connectIsNull()&&channel.isActive();
	}

	// 因为连接是异步的，该方法是同步的，需要先判断链接是否建立
	private boolean connectIsNull(){
		return channel==null;
	}
	public synchronized void closeConnect(){
			if (!connectIsNull()) {
				channel.close();
			}
		   group.shutdownGracefully();
		   isRunning = false;
	}


}
